package com.petdog.module.admin.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.petdog.infrastructure.entity.AdminOperationLog;
import com.petdog.infrastructure.entity.User;
import com.petdog.infrastructure.mapper.AdminOperationLogMapper;
import com.petdog.infrastructure.mapper.DataStatisticsMapper;
import com.petdog.infrastructure.mapper.UserMapper;
import com.petdog.module.admin.dto.AdminDashboardDto;
import com.petdog.module.admin.dto.AdminDashboardDto.DailyStat;
import com.petdog.module.admin.dto.AdminDashboardDto.ContentDistributionDto;
import com.petdog.module.admin.dto.AdminDashboardDto.CommunityActivityDto;
import com.petdog.module.admin.dto.AdminDashboardDto.AiRecognitionDataDto;
import com.petdog.module.admin.dto.AdminUserManageDto;
import com.petdog.module.admin.dto.ContentReviewDto;
import com.petdog.module.admin.dto.OperationLogQueryRequest;
import com.petdog.module.admin.service.AdminService;
import com.petdog.common.dto.PageResult;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.File;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import com.petdog.common.util.CSVUtil;
import com.petdog.common.util.FileUploadUtil;
import com.petdog.infrastructure.entity.BreedInfo;
import com.petdog.module.recognition.service.BreedInfoService;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.util.CollectionUtils;

/**
 * 管理员服务实现类
 */
@Service
@Slf4j
public class AdminServiceImpl implements AdminService {

    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private BreedInfoService breedInfoService;

    @Autowired
    private AdminOperationLogMapper adminOperationLogMapper;

    @Autowired
    private DataStatisticsMapper dataStatisticsMapper;

    @Autowired
    private PasswordEncoder passwordEncoder;

    // 系统上线日期（示例值）
    private static final LocalDate SYSTEM_LAUNCH_DATE = LocalDate.of(2023, 1, 1);

    @Override
    public AdminDashboardDto getDashboardData() {
        // 默认查询近7天的数据
        LocalDate today = LocalDate.now();
        LocalDate startDate = today.minusDays(6);
        return getDashboardDataByTimeRange(startDate, today, "all");
    }

    @Override
    public AdminDashboardDto getDashboardDataByTimeRange(LocalDate startDate, LocalDate endDate, String indicators) {
        try {
            // 参数验证
            validateTimeRange(startDate, endDate);

            AdminDashboardDto dashboard = new AdminDashboardDto();

            // 设置核心指标
            dashboard.setTotalUsers(dataStatisticsMapper.countTotalUsers());
            dashboard.setTotalPets(dataStatisticsMapper.countTotalPets());
            dashboard.setTotalCommunities(dataStatisticsMapper.countTotalCommunities());
            dashboard.setActiveCommunities(dataStatisticsMapper.countActiveCommunities());
            dashboard.setTotalPosts(dataStatisticsMapper.countTotalPosts());
            dashboard.setTodayRecognitions(dataStatisticsMapper.countTodayRecognitions());
            dashboard.setTotalRecognitions(dataStatisticsMapper.countTotalRecognitions());
            dashboard.setTodayActiveUsers(dataStatisticsMapper.countTodayActiveUsers());
            dashboard.setTodayNewUsers(dataStatisticsMapper.countTodayNewUsers());
            dashboard.setTodayNewPosts(dataStatisticsMapper.countTodayNewPosts());

            // 计算平均活跃度 (示例逻辑)
            long totalUsers = dataStatisticsMapper.countTotalUsers();
            long activeUsers = dataStatisticsMapper.countTodayActiveUsers();
            if (totalUsers > 0) {
                dashboard.setAverageActiveRate((double) activeUsers / totalUsers * 100);
            }

            // 计算识别准确率和拦截率 (示例逻辑)
            long totalRecog = dataStatisticsMapper.countTotalRecognitions();
            if (totalRecog > 0) {
                // 假设85%的识别准确率
                dashboard.setRecognitionAccuracy(85.0);
                // 假设5%的拦截率
                dashboard.setRecognitionInterceptRate(5.0);
            }

            // 获取每日统计数据
            List<AdminDashboardDto.DailyStat> dailyStats = dataStatisticsMapper.getDailyStats(startDate, endDate);
            if (dailyStats == null || dailyStats.isEmpty()) {
                // 如果没有数据，填充空数据
                dailyStats = generateEmptyDailyStats(startDate, endDate);
            }
            dashboard.setDailyStats(dailyStats);

            // 获取内容分布数据
            AdminDashboardDto.ContentDistributionDto contentDistribution = dataStatisticsMapper.getContentDistribution(startDate, endDate);
            if (contentDistribution == null) {
                contentDistribution = generateEmptyContentDistribution();
            }
            dashboard.setContentDistribution(contentDistribution);

            // 获取社区活跃度数据
            AdminDashboardDto.CommunityActivityDto communityActivity = dataStatisticsMapper.getCommunityActivity(startDate, endDate);
            if (communityActivity == null) {
                communityActivity = generateEmptyCommunityActivity();
            }
            dashboard.setCommunityActivity(communityActivity);

            // 获取AI识别数据
            AdminDashboardDto.AiRecognitionDataDto aiRecognitionData = dataStatisticsMapper.getAiRecognitionData(startDate, endDate);
            if (aiRecognitionData == null) {
                aiRecognitionData = generateEmptyAiRecognitionData();
            }
            dashboard.setAiRecognitionData(aiRecognitionData);

            return dashboard;
        } catch (IllegalArgumentException e) {
            log.error("时间范围参数验证失败: {}", e.getMessage());
            throw e;
        } catch (Exception e) {
            log.error("获取数据看板失败: {}", e.getMessage());
            throw new RuntimeException("数据加载失败，请刷新页面重试");
        }
    }

    @Override
    public void exportDashboardData(LocalDate startDate, LocalDate endDate, String dataType, HttpServletResponse response) {
        try {
            // 参数验证
            validateTimeRange(startDate, endDate);
            validateExportType(dataType);

            // 设置响应头
            String fileName = String.format("数据统计_%s_%s_%s.xlsx", 
                    dataType, 
                    startDate.format(DateTimeFormatter.ofPattern("yyyyMMdd")), 
                    endDate.format(DateTimeFormatter.ofPattern("yyyyMMdd")));
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            fileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%");
            response.setHeader("Content-disposition", "attachment;filename*=UTF-8''" + fileName);

            // 创建Excel写入策略
            WriteCellStyle headWriteCellStyle = new WriteCellStyle();
            headWriteCellStyle.setFillForegroundColor(IndexedColors.LIGHT_BLUE.getIndex());
            WriteFont headWriteFont = new WriteFont();
            headWriteFont.setFontHeightInPoints((short) 12);
            headWriteFont.setBold(true);
            headWriteCellStyle.setWriteFont(headWriteFont);
            headWriteCellStyle.setBorderBottom(BorderStyle.THIN);
            headWriteCellStyle.setBorderLeft(BorderStyle.THIN);
            headWriteCellStyle.setBorderRight(BorderStyle.THIN);
            headWriteCellStyle.setBorderTop(BorderStyle.THIN);
            headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
            headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);

            WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
            contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);
            contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);
            contentWriteCellStyle.setBorderRight(BorderStyle.THIN);
            contentWriteCellStyle.setBorderTop(BorderStyle.THIN);
            contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
            contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);

            HorizontalCellStyleStrategy styleStrategy = new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);

            // 获取数据
            AdminDashboardDto dashboardData = getDashboardDataByTimeRange(startDate, endDate, "all");

            // 创建Excel写入器
            try (var excelWriter = EasyExcel.write(response.getOutputStream()).registerWriteHandler(styleStrategy).build()) {
                // 写入汇总数据表
                writeSummarySheet(excelWriter, dashboardData, startDate, endDate);

                // 根据数据类型写入相应的数据表
                if ("all".equals(dataType) || "user".equals(dataType)) {
                    writeUserDataSheet(excelWriter, dashboardData, startDate, endDate);
                }

                if ("all".equals(dataType) || "content".equals(dataType)) {
                    writeContentDataSheet(excelWriter, dashboardData, startDate, endDate);
                }

                if ("all".equals(dataType) || "community".equals(dataType)) {
                    writeCommunityDataSheet(excelWriter, dashboardData, startDate, endDate);
                }

                if ("all".equals(dataType)) {
                    writeAiRecognitionDataSheet(excelWriter, dashboardData, startDate, endDate);
                }
            }

            log.info("数据导出成功: 类型={}, 开始日期={}, 结束日期={}", dataType, startDate, endDate);

        } catch (IllegalArgumentException e) {
            log.error("导出参数验证失败: {}", e.getMessage());
            throw e;
        } catch (IOException e) {
            log.error("文件生成失败: {}", e.getMessage());
            throw new RuntimeException("文件导出异常，请检查数据量或稍后重试");
        } catch (Exception e) {
            log.error("数据导出失败: {}", e.getMessage());
            throw new RuntimeException("文件导出异常，请检查数据量或稍后重试");
        }
    }

    // 私有辅助方法
    private void validateTimeRange(LocalDate startDate, LocalDate endDate) {
        if (startDate == null || endDate == null) {
            throw new IllegalArgumentException("请选择有效的时间范围");
        }

        if (startDate.isAfter(endDate)) {
            throw new IllegalArgumentException("开始时间必须早于或等于结束时间");
        }

        // 检查时间范围跨度是否超过365天
        long daysBetween = java.time.temporal.ChronoUnit.DAYS.between(startDate, endDate);
        if (daysBetween > 365) {
            throw new IllegalArgumentException("时间范围跨度不能超过365天");
        }

        // 检查开始时间是否早于系统上线日期
        if (startDate.isBefore(SYSTEM_LAUNCH_DATE)) {
            throw new IllegalArgumentException("开始时间不能早于系统上线日期");
        }
    }

    private void validateExportType(String dataType) {
        Set<String> validTypes = new HashSet<>(Arrays.asList("user", "content", "community", "all"));
        if (dataType == null || !validTypes.contains(dataType)) {
            throw new IllegalArgumentException("导出类型必须是user、content、community或all");
        }
    }

    private List<AdminDashboardDto.DailyStat> generateEmptyDailyStats(LocalDate startDate, LocalDate endDate) {
        List<AdminDashboardDto.DailyStat> stats = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd");
        LocalDate current = startDate;

        while (!current.isAfter(endDate)) {
            AdminDashboardDto.DailyStat stat = new AdminDashboardDto.DailyStat();
            stat.setDate(current.format(formatter));
            stat.setUserCount(0L);
            stat.setPostCount(0L);
            stat.setRecognitionCount(0L);
            stat.setCommentCount(0L);
            stat.setLikeCount(0L);
            stat.setActiveUserCount(0L);
            stats.add(stat);
            current = current.plusDays(1);
        }

        return stats;
    }

    private AdminDashboardDto.ContentDistributionDto generateEmptyContentDistribution() {
        AdminDashboardDto.ContentDistributionDto distribution = new AdminDashboardDto.ContentDistributionDto();
        distribution.setCategories(Arrays.asList("帖子", "评论", "点赞"));
        distribution.setPostCounts(Arrays.asList(0L, 0L, 0L));
        distribution.setCommentCounts(Arrays.asList(0L, 0L, 0L));
        distribution.setLikeCounts(Arrays.asList(0L, 0L, 0L));
        return distribution;
    }

    private AdminDashboardDto.CommunityActivityDto generateEmptyCommunityActivity() {
        AdminDashboardDto.CommunityActivityDto activity = new AdminDashboardDto.CommunityActivityDto();
        activity.setLabels(Arrays.asList("活跃社区", "非活跃社区"));
        activity.setValues(Arrays.asList(0L, 0L));
        activity.setColors(Arrays.asList("#52c41a", "#d9d9d9"));
        return activity;
    }

    private AdminDashboardDto.AiRecognitionDataDto generateEmptyAiRecognitionData() {
        AdminDashboardDto.AiRecognitionDataDto aiData = new AdminDashboardDto.AiRecognitionDataDto();
        aiData.setTotalRecognitionCount(0L);
        aiData.setSuccessRecognitionCount(0L);
        aiData.setInterceptedCount(0L);
        aiData.setAccuracyRate(0.0);
        aiData.setInterceptRate(0.0);
        aiData.setBreedLabels(Collections.emptyList());
        aiData.setBreedCounts(Collections.emptyList());
        return aiData;
    }

    // Excel导出辅助方法
    private void writeSummarySheet(com.alibaba.excel.ExcelWriter excelWriter, AdminDashboardDto data, LocalDate startDate, LocalDate endDate) {
        List<List<String>> dataList = new ArrayList<>();
        
        // 添加标题行
        dataList.add(Arrays.asList("数据统计汇总表", "", "时间范围: " + startDate + " 至 " + endDate));
        dataList.add(Arrays.asList("", "", ""));
        
        // 添加数据行
        dataList.add(Arrays.asList("核心指标", "数值", "说明"));
        dataList.add(Arrays.asList("总用户数", String.valueOf(data.getTotalUsers() == null ? 0 : data.getTotalUsers()), "平台注册用户总数"));
        dataList.add(Arrays.asList("今日新增用户", String.valueOf(data.getTodayNewUsers() == null ? 0 : data.getTodayNewUsers()), "今日新增注册用户数"));
        dataList.add(Arrays.asList("总宠物数", String.valueOf(data.getTotalPets() == null ? 0 : data.getTotalPets()), "平台注册宠物总数"));
        dataList.add(Arrays.asList("总社区数", String.valueOf(data.getTotalCommunities() == null ? 0 : data.getTotalCommunities()), "平台创建的社区总数"));
        dataList.add(Arrays.asList("活跃社区数", String.valueOf(data.getActiveCommunities() == null ? 0 : data.getActiveCommunities()), "近期有活动的社区数"));
        dataList.add(Arrays.asList("总内容数", String.valueOf(data.getTotalPosts() == null ? 0 : data.getTotalPosts()), "平台发布的内容总数"));
        dataList.add(Arrays.asList("今日新增内容", String.valueOf(data.getTodayNewPosts() == null ? 0 : data.getTodayNewPosts()), "今日发布的内容数"));
        dataList.add(Arrays.asList("今日识别次数", String.valueOf(data.getTodayRecognitions() == null ? 0 : data.getTodayRecognitions()), "今日AI识别请求次数"));
        dataList.add(Arrays.asList("总识别次数", String.valueOf(data.getTotalRecognitions() == null ? 0 : data.getTotalRecognitions()), "平台总AI识别请求次数"));
        dataList.add(Arrays.asList("今日活跃用户", String.valueOf(data.getTodayActiveUsers() == null ? 0 : data.getTodayActiveUsers()), "今日有登录或操作的用户数"));
        
        // 写入Excel
        var sheet = EasyExcel.writerSheet("数据汇总").build();
        excelWriter.write(dataList, sheet);
    }

    private void writeUserDataSheet(com.alibaba.excel.ExcelWriter excelWriter, AdminDashboardDto data, LocalDate startDate, LocalDate endDate) {
        List<List<String>> dataList = new ArrayList<>();
        
        // 添加标题行
        dataList.add(Arrays.asList("用户数据统计", "", "时间范围: " + startDate + " 至 " + endDate));
        dataList.add(Arrays.asList("", "", ""));
        
        // 添加表头
        dataList.add(Arrays.asList("日期", "新增用户数", "活跃用户数", "用户总数"));
        
        // 添加每日数据
        if (data.getDailyStats() != null) {
            for (AdminDashboardDto.DailyStat stat : data.getDailyStats()) {
                dataList.add(Arrays.asList(
                        stat.getDate(),
                        String.valueOf(stat.getUserCount() == null ? 0 : stat.getUserCount()),
                        String.valueOf(stat.getActiveUserCount() == null ? 0 : stat.getActiveUserCount()),
                        String.valueOf(data.getTotalUsers() == null ? 0 : data.getTotalUsers())
                ));
            }
        }
        
        // 写入Excel
        var sheet = EasyExcel.writerSheet("用户数据").build();
        excelWriter.write(dataList, sheet);
    }

    private void writeContentDataSheet(com.alibaba.excel.ExcelWriter excelWriter, AdminDashboardDto data, LocalDate startDate, LocalDate endDate) {
        List<List<String>> dataList = new ArrayList<>();
        
        // 添加标题行
        dataList.add(Arrays.asList("内容数据统计", "", "时间范围: " + startDate + " 至 " + endDate));
        dataList.add(Arrays.asList("", "", ""));
        
        // 添加表头
        dataList.add(Arrays.asList("日期", "新增帖子数", "评论数", "点赞数"));
        
        // 添加每日数据
        if (data.getDailyStats() != null) {
            for (AdminDashboardDto.DailyStat stat : data.getDailyStats()) {
                dataList.add(Arrays.asList(
                        stat.getDate(),
                        String.valueOf(stat.getPostCount() == null ? 0 : stat.getPostCount()),
                        String.valueOf(stat.getCommentCount() == null ? 0 : stat.getCommentCount()),
                        String.valueOf(stat.getLikeCount() == null ? 0 : stat.getLikeCount())
                ));
            }
        }
        
        // 写入Excel
        var sheet = EasyExcel.writerSheet("内容数据").build();
        excelWriter.write(dataList, sheet);
    }

    private void writeCommunityDataSheet(com.alibaba.excel.ExcelWriter excelWriter, AdminDashboardDto data, LocalDate startDate, LocalDate endDate) {
        List<List<String>> dataList = new ArrayList<>();
        
        // 添加标题行
        dataList.add(Arrays.asList("社区数据统计", "", "时间范围: " + startDate + " 至 " + endDate));
        dataList.add(Arrays.asList("", "", ""));
        
        // 添加社区活跃度数据
        dataList.add(Arrays.asList("社区类型", "数量", "占比"));
        
        if (data.getCommunityActivity() != null && data.getCommunityActivity().getLabels() != null && data.getCommunityActivity().getValues() != null) {
            List<String> labels = data.getCommunityActivity().getLabels();
            List<Long> values = data.getCommunityActivity().getValues();
            
            // 计算总数
            long total = values.stream().mapToLong(Long::longValue).sum();
            
            for (int i = 0; i < labels.size() && i < values.size(); i++) {
                String percentage = total > 0 ? String.format("%.2f%%", (double) values.get(i) / total * 100) : "0.00%";
                dataList.add(Arrays.asList(
                        labels.get(i),
                        String.valueOf(values.get(i)),
                        percentage
                ));
            }
        }
        
        // 写入Excel
        var sheet = EasyExcel.writerSheet("社区数据").build();
        excelWriter.write(dataList, sheet);
    }

    private void writeAiRecognitionDataSheet(com.alibaba.excel.ExcelWriter excelWriter, AdminDashboardDto data, LocalDate startDate, LocalDate endDate) {
        List<List<String>> dataList = new ArrayList<>();
        
        // 添加标题行
        dataList.add(Arrays.asList("AI识别数据统计", "", "时间范围: " + startDate + " 至 " + endDate));
        dataList.add(Arrays.asList("", "", ""));
        
        // 添加AI识别汇总数据
        dataList.add(Arrays.asList("指标", "数值"));
        
        if (data.getAiRecognitionData() != null) {
            AdminDashboardDto.AiRecognitionDataDto aiData = data.getAiRecognitionData();
            dataList.add(Arrays.asList("总识别次数", String.valueOf(aiData.getTotalRecognitionCount() == null ? 0 : aiData.getTotalRecognitionCount())));
            dataList.add(Arrays.asList("成功识别次数", String.valueOf(aiData.getSuccessRecognitionCount() == null ? 0 : aiData.getSuccessRecognitionCount())));
            dataList.add(Arrays.asList("拦截次数", String.valueOf(aiData.getInterceptedCount() == null ? 0 : aiData.getInterceptedCount())));
            dataList.add(Arrays.asList("准确率", String.format("%.2f%%", aiData.getAccuracyRate() == null ? 0 : aiData.getAccuracyRate())));
            dataList.add(Arrays.asList("拦截率", String.format("%.2f%%", aiData.getInterceptRate() == null ? 0 : aiData.getInterceptRate())));
        }
        
        // 写入Excel
        var sheet = EasyExcel.writerSheet("AI识别数据").build();
        excelWriter.write(dataList, sheet);
    }

    @Override
    public PageResult<AdminUserManageDto> getUserList(Integer pageNum, Integer pageSize, String username, String email, Integer status) {
        // 计算分页
        int offset = (pageNum - 1) * pageSize;
        // UserMapper中的方法需要phone参数，这里传入null
        List<User> users = userMapper.selectUserList(offset, pageSize, username, null, email, status);
        long total = userMapper.countUserList(username, null, email, status);

        // 转换为DTO
        List<AdminUserManageDto> dtoList = new ArrayList<>();
        for (User user : users) {
            AdminUserManageDto dto = new AdminUserManageDto();
            BeanUtils.copyProperties(user, dto);
            dtoList.add(dto);
        }

        return new PageResult<>(dtoList, pageNum, pageSize, total);
    }

    @Override
    public boolean updateUserStatus(Long userId, Integer status) {
        User user = new User();
        user.setUserId(userId);
        user.setStatus(status);
        user.setUpdateTime(LocalDateTime.now());
        return userMapper.update(user) > 0;
    }

    @Override
    public boolean resetUserPassword(Long userId) {
        // 重置密码为123456（加密后）
        User user = new User();
        user.setUserId(userId);
        user.setPassword(passwordEncoder.encode("123456"));
        user.setUpdateTime(LocalDateTime.now());
        return userMapper.update(user) > 0;
    }

    /**
     * 获取内容审核列表
     */
    @Override
    public PageResult<ContentReviewDto> getContentReviewList(Integer pageNum, Integer pageSize, String contentType, Integer status) {
        // 验证参数
        if (pageNum < 1 || pageSize < 1 || pageSize > 100) {
            throw new IllegalArgumentException("页码或页大小参数无效");
        }
        
        if (!"post".equals(contentType) && !"comment".equals(contentType)) {
            throw new IllegalArgumentException("内容类型参数无效");
        }
        
        log.info("获取内容审核列表: contentType={}, status={}, pageNum={}, pageSize={}", 
                contentType, status, pageNum, pageSize);
        
        // 模拟数据
        List<ContentReviewDto> contentList = generateMockReviewData(contentType, status);
        
        // 计算总数和分页
        long total = contentList.size();
        int start = (pageNum - 1) * pageSize;
        int end = Math.min(start + pageSize, contentList.size());
        List<ContentReviewDto> pageList = contentList.subList(start, end);
        
        // 返回分页结果
        return new PageResult<>(pageList, pageNum, pageSize, total);
    }
    
    /**
     * 生成模拟审核数据
     */
    private List<ContentReviewDto> generateMockReviewData(String contentType, Integer status) {
        List<ContentReviewDto> contentList = new ArrayList<>();
        
        // 生成10条模拟数据
        for (int i = 1; i <= 10; i++) {
            ContentReviewDto dto = new ContentReviewDto();
            dto.setContentId((long) i);
            dto.setContentType(contentType);
            
            if ("post".equals(contentType)) {
                dto.setTitle("这是测试帖子标题 " + i);
                dto.setContent("这是帖子内容，包含一些测试文字和信息。\n第二行内容。");
                dto.setImageUrls("https://example.com/image1.jpg,https://example.com/image2.jpg");
            } else {
                dto.setContent("这是评论内容，用于测试内容审核功能。");
            }
            
            dto.setUserId((long) (1000 + i));
            dto.setUsername("user" + i);
            dto.setPublishTime(LocalDateTime.now().minusHours(i));
            
            // 如果指定了状态，则只返回该状态的数据
            if (status == null) {
                // 随机分配状态
                dto.setStatus(i % 3); // 0:待审核, 1:已通过, 2:已拒绝
            } else {
                dto.setStatus(status);
            }
            
            // 添加预审核结果
            if (i % 5 == 0) {
                dto.setPreReviewResult("[警告] 包含潜在敏感词，请人工确认");
            } else {
                dto.setPreReviewResult("[正常] 未发现违规内容");
            }
            
            // 已审核的内容添加审核信息
            if (dto.getStatus() == 1 || dto.getStatus() == 2) {
                dto.setReviewTime(LocalDateTime.now().minusMinutes(i * 5));
                dto.setReviewer("admin");
                dto.setReviewNote("内容审核通过");
            }
            
            contentList.add(dto);
        }
        
        return contentList;
    }

    /**
     * 审核内容
     */
    @Override
    public boolean reviewContent(Long contentId, String contentType, Integer status, String reviewNote) {
        // 验证参数
        if (contentId == null || contentId <= 0) {
            throw new IllegalArgumentException("操作内容不存在，请刷新列表后重试");
        }
        
        if (!"post".equals(contentType) && !"comment".equals(contentType)) {
            throw new IllegalArgumentException("内容类型参数无效");
        }
        
        if (status == null || (status != 1 && status != 2)) {
            throw new IllegalArgumentException("审核状态参数无效");
        }
        
        // 拒绝时必须填写审核原因
        if (status == 2 && (reviewNote == null || reviewNote.trim().isEmpty())) {
            throw new IllegalArgumentException("拒绝操作需填写原因，请补充后提交");
        }
        
        // 审核原因长度限制
        if (reviewNote != null && reviewNote.length() > 200) {
            throw new IllegalArgumentException("审核原因不能超过200字符");
        }
        
        log.info("审核内容: contentId={}, contentType={}, status={}", contentId, contentType, status);
        
        // 模拟审核操作
        // 在实际项目中，这里应该更新数据库中对应内容的状态
        log.info("内容审核成功，contentId={}, 状态更新为={}", contentId, status);
        
        // 记录审核日志
        saveReviewLog(contentId, contentType, status, reviewNote);
        
        return true;
    }
    
    /**
     * 编辑内容文本
     */
    @Override
    public boolean editContent(Long contentId, String contentType, String editedContent) {
        // 验证参数
        if (contentId == null || contentId <= 0) {
            throw new IllegalArgumentException("操作内容不存在，请刷新列表后重试");
        }
        
        if (!"post".equals(contentType) && !"comment".equals(contentType)) {
            throw new IllegalArgumentException("内容类型参数无效");
        }
        
        if (editedContent == null || editedContent.trim().isEmpty()) {
            throw new IllegalArgumentException("编辑内容不能为空");
        }
        
        // 内容长度限制
        if (editedContent.length() > 2000) {
            throw new IllegalArgumentException("编辑内容不能超过2000字符");
        }
        
        log.info("编辑内容: contentId={}, contentType={}", contentId, contentType);
        
        // 模拟内容编辑操作
        // 在实际项目中，这里应该更新数据库中对应内容的文本
        log.info("内容编辑成功，contentId={}", contentId);
        
        // 记录编辑日志
        saveOperationLog(createOperationLog("content", "edit", 
                "编辑内容: ID=" + contentId + ", 类型=" + contentType));
        
        // 模拟重新进行预审核
        simulatePreReview(contentId, contentType, editedContent);
        
        return true;
    }
    
    /**
     * 删除内容（支持单条或批量）
     */
    @Override
    public boolean deleteContent(List<Long> contentIds, String contentType, String deleteReason) {
        // 验证参数
        if (contentIds == null || contentIds.isEmpty()) {
            throw new IllegalArgumentException("请选择要删除的内容");
        }
        
        if (contentIds.size() > 50) {
            throw new IllegalArgumentException("批量操作最多选择50条内容，请调整选择");
        }
        
        if (!"post".equals(contentType) && !"comment".equals(contentType)) {
            throw new IllegalArgumentException("内容类型参数无效");
        }
        
        if (deleteReason == null || deleteReason.trim().isEmpty()) {
            throw new IllegalArgumentException("删除操作需填写原因，请补充后提交");
        }
        
        // 删除原因长度限制
        if (deleteReason.length() > 200) {
            throw new IllegalArgumentException("删除原因不能超过200字符");
        }
        
        log.info("删除内容: 数量={}, contentType={}", contentIds.size(), contentType);
        
        // 模拟删除操作
        // 在实际项目中，这里应该更新数据库中对应内容的状态为已删除
        log.info("内容删除成功，数量={}", contentIds.size());
        
        // 记录删除日志
        saveOperationLog(createOperationLog("content", "delete", 
                "删除内容: 数量=" + contentIds.size() + ", 类型=" + contentType + ", 原因=" + deleteReason));
        
        return true;
    }
    
    /**
     * 记录审核日志
     */
    private void saveReviewLog(Long contentId, String contentType, Integer status, String reviewNote) {
        // 在实际项目中，这里应该保存审核记录到数据库
        String statusText = status == 1 ? "通过" : "拒绝";
        log.info("记录审核日志: contentId={}, contentType={}, status={}, reviewNote={}", 
                contentId, contentType, statusText, reviewNote);
        
        // 同时保存到操作日志
        saveOperationLog(createOperationLog("review", "process", 
                "审核内容: ID=" + contentId + ", 类型=" + contentType + ", 状态=" + statusText + ", 备注=" + reviewNote));
    }
    
    /**
     * 模拟重新预审核
     */
    private void simulatePreReview(Long contentId, String contentType, String content) {
        // 在实际项目中，这里应该调用敏感词检测和图像识别服务
            log.info("对内容进行重新预审核: contentId={}, contentType={}", contentId, contentType);
            
            // 简单模拟预审核逻辑
            if (content.contains("敏感词") || content.contains("违规")) {
                log.info("重新预审核结果: 检测到潜在问题，建议人工复核");
            } else {
                log.info("重新预审核结果: 未发现违规内容");
            }
    }
    
    /**
     * 创建操作日志对象
     */
    private AdminOperationLog createOperationLog(String module, String type, String desc) {
        AdminOperationLog log = new AdminOperationLog();
        log.setAdminId(1L); // 示例值
        log.setAdminUsername("admin"); // 示例值
        log.setOperationType(type);
        log.setOperationModule(module);
        log.setOperationDesc(desc);
        log.setRequestParams("{}");
        log.setRequestIp("127.0.0.1"); // 示例值
        log.setUserAgent("AdminBrowser"); // 示例值
        log.setStatus(1);
        return log;
    }

    @Override
    public PageResult<AdminOperationLog> getOperationLogList(OperationLogQueryRequest request) {
        // 计算分页
            int offset = (request.getPageNum() - 1) * request.getPageSize();
            List<AdminOperationLog> logs = adminOperationLogMapper.selectLogList(
                    offset, 
                    request.getPageSize(), 
                    request.getAdminId(), 
                    request.getOperationType(), 
                    request.getOperationModule(), 
                    request.getStartTime(), 
                    request.getEndTime()
            );
        long total = adminOperationLogMapper.countLogList(
                request.getAdminId(), 
                request.getOperationType(), 
                request.getOperationModule(), 
                request.getStartTime(), 
                request.getEndTime()
        );

        return new PageResult<>(logs, request.getPageNum(), request.getPageSize(), total);
    }

    @Override
    public void saveOperationLog(AdminOperationLog operationLog) {
        operationLog.setCreateTime(LocalDateTime.now());
        try {
                adminOperationLogMapper.insert(operationLog);
            } catch (Exception e) {
                // 记录失败不影响主业务流程
                log.error("操作日志记录失败: {}", e.getMessage());
            }
    }
    
    @Override
    public void exportOperationLogsToCSV(OperationLogQueryRequest request, HttpServletResponse response) {
        // 取消分页限制，导出所有符合条件的数据
        request.setPageNum(1);
        request.setPageSize(Integer.MAX_VALUE);
        
        try {
            // 查询操作日志
            List<AdminOperationLog> logs = adminOperationLogMapper.selectLogList(
                    0, 
                    Integer.MAX_VALUE, 
                    request.getAdminId(), 
                    request.getOperationType(), 
                    request.getOperationModule(), 
                    request.getStartTime(), 
                    request.getEndTime()
            );
            
            // 转换为CSV数据格式
            List<String[]> csvData = new ArrayList<>();
            
            // 定义CSV表头
            String[] headers = {
                "日志ID",
                "管理员ID",
                "管理员用户名",
                "操作类型",
                "操作模块",
                "操作描述",
                "请求参数",
                "IP地址",
                "用户代理",
                "状态",
                "操作时间"
            };
            
            // 准备数据行
            for (AdminOperationLog log : logs) {
                String statusText = log.getStatus() == 1 ? "成功" : "失败";
                
                String[] row = {
                    log.getLogId() != null ? log.getLogId().toString() : "",
                    log.getAdminId() != null ? log.getAdminId().toString() : "",
                    log.getAdminUsername() != null ? log.getAdminUsername() : "",
                    log.getOperationType() != null ? log.getOperationType() : "",
                    log.getOperationModule() != null ? log.getOperationModule() : "",
                    log.getOperationDesc() != null ? log.getOperationDesc() : "",
                    log.getRequestParams() != null ? log.getRequestParams() : "",
                    log.getRequestIp() != null ? log.getRequestIp() : "",
                    log.getUserAgent() != null ? log.getUserAgent() : "",
                    statusText,
                    log.getCreateTime() != null ? 
                            log.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) : ""
                };
                csvData.add(row);
            }
            
            // 创建带时间戳的文件名
            String fileName = CSVUtil.createTimestampedFileName("操作日志");
            
            // 设置HTTP响应头
            CSVUtil.setCSVResponseHeaders(response, fileName);
            
            // 写入CSV文件
            CSVUtil.writeCSV(csvData, headers, response.getOutputStream());
            
        } catch (Exception e) {
            log.error("导出操作日志失败: {}", e.getMessage());
            throw new RuntimeException("日志导出失败（可能因数据量过大或网络问题），请重试或缩小查询范围", e);
        }
    }

    // 以下是品种知识库维护相关方法的实现

    /**
     * 获取品种列表（支持分页、搜索、筛选）
     */
    @Override
    public PageResult getBreedList(Integer pageNum, Integer pageSize, String keyword, String sizeCategory) {
        // 验证参数
        if (pageNum == null || pageNum <= 0) {
            pageNum = 1;
        }
        if (pageSize == null || pageSize <= 0) {
            pageSize = 10;
        }
        if (pageSize > 100) {
            pageSize = 100;
        }

        log.info("获取品种列表，pageNum={}, pageSize={}, keyword={}, sizeCategory={}", 
                pageNum, pageSize, keyword, sizeCategory);

        try {
            // 获取所有品种
            List<BreedInfo> allBreeds = breedInfoService.getAllBreeds();
            if (CollectionUtils.isEmpty(allBreeds)) {
                return new PageResult<>(Collections.emptyList(), pageNum, pageSize, 0L);
            }

            // 搜索和筛选
            List<BreedInfo> filteredBreeds = allBreeds.stream()
                    .filter(breed -> {
                        // 关键词搜索
                        boolean keywordMatch = (keyword == null || keyword.trim().isEmpty()) ||
                                breed.getBreedName().contains(keyword) ||
                                breed.getScientificName().contains(keyword) ||
                                breed.getOriginCountry().contains(keyword);
                        
                        // 体型筛选
                        boolean sizeMatch = (sizeCategory == null || sizeCategory.trim().isEmpty()) ||
                                sizeCategory.equals("all") ||
                                breed.getSize().equals(sizeCategory);
                        
                        return keywordMatch && sizeMatch;
                    })
                    .collect(Collectors.toList());

            // 分页
            int total = filteredBreeds.size();
            int startIndex = (pageNum - 1) * pageSize;
            int endIndex = Math.min(startIndex + pageSize, total);
            
            List<BreedInfo> pageBreeds = startIndex < total ? 
                    filteredBreeds.subList(startIndex, endIndex) : 
                    Collections.emptyList();

            // 记录操作日志
            saveOperationLog(createOperationLog("breed", "list", 
                    "获取品种列表: 页码=" + pageNum + ", 每页数量=" + pageSize + ", 关键词=" + keyword));

            return new PageResult<>(pageBreeds, pageNum, pageSize, (long) total);
        } catch (Exception e) {
            log.error("获取品种列表失败", e);
            throw new RuntimeException("获取品种列表失败", e);
        }
    }

    /**
     * 创建新品种
     */
    @Override
    public boolean createBreed(BreedInfo breedInfo, List<MultipartFile> images) {
        // 参数验证
        validateBreedInfo(breedInfo, null);
        validateBreedImages(images);
        
        // 检查名称是否已存在
        if (checkBreedNameExists(breedInfo.getBreedName(), null)) {
            throw new IllegalArgumentException("品种名称已存在，请更换名称后提交");
        }

        try {
            // 上传图片
            List<String> imageUrls = uploadBreedImages(images);
            if (!imageUrls.isEmpty()) {
                // 保存第一张图片作为主图
                breedInfo.setImageUrl(imageUrls.get(0));
            }

            // 保存品种信息
            boolean success = breedInfoService.saveBreed(breedInfo);
            if (success) {
                log.info("创建品种成功，名称={}", breedInfo.getBreedName());
                // 记录操作日志
                saveOperationLog(createOperationLog("breed", "create", 
                        "创建新品种: 名称=" + breedInfo.getBreedName()));
            }
            return success;
        } catch (IllegalArgumentException e) {
            throw e;
        } catch (Exception e) {
            log.error("创建品种失败", e);
            throw new RuntimeException("创建品种失败: " + e.getMessage(), e);
        }
    }

    /**
     * 更新品种信息
     */
    @Override
    public boolean updateBreed(Integer breedId, BreedInfo breedInfo, List<MultipartFile> images) {
        // 验证参数
        if (breedId == null || breedId <= 0) {
            throw new IllegalArgumentException("品种ID无效");
        }
        
        // 检查品种是否存在
        BreedInfo existingBreed = breedInfoService.getBreedById(breedId);
        if (existingBreed == null) {
            throw new IllegalArgumentException("未找到该品种信息");
        }
        
        // 验证品种信息
        validateBreedInfo(breedInfo, breedId);
        
        // 如果有新图片，则验证图片
        if (images != null && !images.isEmpty()) {
            validateBreedImages(images);
        }

        try {
            // 设置ID
            breedInfo.setBreedId(breedId);
            
            // 如果提供了新图片，则上传
            if (images != null && !images.isEmpty()) {
                List<String> imageUrls = uploadBreedImages(images);
                if (!imageUrls.isEmpty()) {
                    breedInfo.setImageUrl(imageUrls.get(0));
                }
            } else {
                // 保留原图片
                breedInfo.setImageUrl(existingBreed.getImageUrl());
            }

            // 更新品种信息
            boolean success = breedInfoService.saveBreed(breedInfo);
            if (success) {
                    log.info("更新品种成功，ID={}, 名称={}", breedId, breedInfo.getBreedName());
                    // 记录操作日志
                    saveOperationLog(createOperationLog("breed", "update", 
                            "更新品种: ID=" + breedId + ", 名称=" + breedInfo.getBreedName()));
                }
            return success;
        } catch (IllegalArgumentException e) {
            throw e;
        } catch (Exception e) {
            log.error("更新品种失败", e);
            throw new RuntimeException("更新品种失败: " + e.getMessage(), e);
        }
    }

    /**
     * 删除品种
     */
    @Override
    public boolean deleteBreed(Integer breedId) {
        // 验证参数
        if (breedId == null || breedId <= 0) {
            throw new IllegalArgumentException("品种ID无效");
        }
        
        // 检查品种是否存在
        BreedInfo breedInfo = breedInfoService.getBreedById(breedId);
        if (breedInfo == null) {
            throw new IllegalArgumentException("未找到该品种信息");
        }

        try {
            // 删除品种
            boolean success = breedInfoService.deleteBreed(breedId);
            if (success) {
                    log.info("删除品种成功，ID={}, 名称={}", breedId, breedInfo.getBreedName());
                    // 记录操作日志
                    saveOperationLog(createOperationLog("breed", "delete", 
                            "删除品种: ID=" + breedId + ", 名称=" + breedInfo.getBreedName()));
                }
            return success;
        } catch (Exception e) {
                log.error("删除品种失败", e);
                // 检查是否有引用冲突
                if (e.getMessage() != null && e.getMessage().contains("constraint")) {
                    throw new RuntimeException("该品种已被引用，无法删除");
                }
                throw new RuntimeException("删除品种失败: " + e.getMessage(), e);
            }
    }

    /**
     * 批量导入品种（从CSV文件）
     */
    @Override
    public Map<String, Object> batchImportBreeds(MultipartFile csvFile) {
        Map<String, Object> result = new HashMap<>();
        int successCount = 0;
        int failCount = 0;
        List<String> errorMessages = new ArrayList<>();

        try {
            // 验证文件
            if (csvFile == null || csvFile.isEmpty()) {
                throw new IllegalArgumentException("请选择要导入的CSV文件");
            }
            
            // 保存临时文件
            File tempFile = File.createTempFile("breeds_", ".csv");
            csvFile.transferTo(tempFile);
            
            try {
                // 检查文件是否为有效的CSV文件
                if (!CSVUtil.isValidCSVFile(tempFile)) {
                    throw new IllegalArgumentException("无效的CSV文件，请检查文件格式");
                }
                
                // 读取CSV内容
                List<String[]> csvData = CSVUtil.readCSV(tempFile, true);
                if (CollectionUtils.isEmpty(csvData)) {
                    throw new IllegalArgumentException("CSV文件内容为空或格式不正确");
                }
                
                // 逐行处理数据
                for (int i = 0; i < csvData.size(); i++) {
                    try {
                        String[] row = csvData.get(i);
                        // 验证行数据
                        if (row.length < 5) { // 至少需要品种名称、学名、原产国、体型、描述
                            failCount++;
                            errorMessages.add("第" + (i + 1) + "行数据不完整");
                            continue;
                        }
                        
                        // 创建品种信息
                        BreedInfo breedInfo = new BreedInfo();
                        breedInfo.setBreedName(row[0].trim());
                        breedInfo.setScientificName(row[1].trim());
                        breedInfo.setOriginCountry(row[2].trim());
                        breedInfo.setSize(row[3].trim());
                        breedInfo.setDescription(row[4].trim());
                        
                        // 其他可选字段
                        if (row.length > 5) {
                            // 解析体重范围
                String weightRange = row[5].trim();
                if (!weightRange.isEmpty()) {
                    try {
                        String[] weights = weightRange.split("-");
                        if (weights.length == 2) {
                            breedInfo.setMinWeight(Float.parseFloat(weights[0].trim()));
                            breedInfo.setMaxWeight(Float.parseFloat(weights[1].trim()));
                        }
                    } catch (NumberFormatException ignored) {}
                }
                        }
                        if (row.length > 6) {
                            // 解析身高范围
                            String heightRange = row[6].trim();
                            if (!heightRange.isEmpty()) {
                                try {
                                    String[] heights = heightRange.split("-");
                                    if (heights.length == 2) {
                                        breedInfo.setMinHeight(Float.parseFloat(heights[0].trim()));
                                        breedInfo.setMaxHeight(Float.parseFloat(heights[1].trim()));
                                    }
                                } catch (NumberFormatException ignored) {}
                            }
                        }
                        if (row.length > 7 && !row[7].trim().isEmpty()) {
                            try {
                                breedInfo.setLifeExpectancy(Integer.parseInt(row[7].trim()));
                            } catch (NumberFormatException ignored) {}
                        }
                        if (row.length > 8) breedInfo.setPersonality(row[8].trim());
                        if (row.length > 9) breedInfo.setAppearance(row[9].trim());
                        
                        // 基本验证
                        validateBreedInfo(breedInfo, null, false); // 不验证图片
                        
                        // 检查名称是否已存在
                        if (checkBreedNameExists(breedInfo.getBreedName(), null)) {
                            failCount++;
                            errorMessages.add("第" + (i + 1) + "行：品种名称\"" + breedInfo.getBreedName() + "\"已存在");
                            continue;
                        }
                        
                        // 保存品种
                        if (breedInfoService.saveBreed(breedInfo)) {
                            successCount++;
                        } else {
                            failCount++;
                            errorMessages.add("第" + (i + 1) + "行：保存失败");
                        }
                    } catch (Exception e) {
                        failCount++;
                        errorMessages.add("第" + (i + 1) + "行：" + e.getMessage());
                    }
                }
            } finally {
                // 清理临时文件
                if (tempFile.exists()) {
                    tempFile.delete();
                }
            }
            
            // 记录操作日志
            saveOperationLog(createOperationLog("breed", "batch-import", 
                    "批量导入品种: 总数量=" + (successCount + failCount) + ", 成功=" + successCount + ", 失败=" + failCount));
            
        } catch (IllegalArgumentException e) {
            throw e;
        } catch (Exception e) {
                log.error("批量导入品种失败", e);
                throw new RuntimeException("批量导入品种失败: " + e.getMessage(), e);
            }
        
        // 设置结果
        result.put("successCount", successCount);
        result.put("failCount", failCount);
        result.put("errorMessages", errorMessages);
        result.put("totalCount", successCount + failCount);
        
        return result;
    }

    /**
     * 检查品种名称是否已存在
     */
    @Override
    public boolean checkBreedNameExists(String breedName, Integer excludeId) {
        if (breedName == null || breedName.trim().isEmpty()) {
            return false;
        }
        
        try {
            BreedInfo breedInfo = breedInfoService.getBreedByName(breedName);
            if (breedInfo == null) {
                return false;
            }
            
            // 如果排除ID不为空，则检查是否是同一个品种
            return excludeId == null || !breedInfo.getBreedId().equals(excludeId);
        } catch (Exception e) {
            log.error("检查品种名称是否存在失败", e);
            return false;
        }
    }

    /**
     * 获取所有体型分类选项
     */
    @Override
    public List<String> getSizeCategories() {
        // 预定义的体型分类
        List<String> categories = new ArrayList<>();
        categories.add("小型犬");
        categories.add("中型犬");
        categories.add("大型犬");
        return categories;
    }

    // 辅助方法

    /**
     * 验证品种信息
     */
    private void validateBreedInfo(BreedInfo breedInfo, Integer excludeId) {
        validateBreedInfo(breedInfo, excludeId, true);
    }

    private void validateBreedInfo(BreedInfo breedInfo, Integer excludeId, boolean validateDescription) {
        if (breedInfo == null) {
            throw new IllegalArgumentException("品种信息不能为空");
        }
        
        // 验证品种名称
        if (breedInfo.getBreedName() == null || breedInfo.getBreedName().trim().isEmpty()) {
            throw new IllegalArgumentException("品种名称必填");
        }
        if (breedInfo.getBreedName().length() > 50) {
            throw new IllegalArgumentException("品种名称不能超过50字符");
        }
        
        // 验证学名
        if (breedInfo.getScientificName() != null && breedInfo.getScientificName().length() > 100) {
            throw new IllegalArgumentException("标准英文名不能超过100字符");
        }
        
        // 验证体型分类
        if (breedInfo.getSize() == null || breedInfo.getSize().trim().isEmpty()) {
            throw new IllegalArgumentException("体型分类必填");
        }
        List<String> validSizes = getSizeCategories();
        if (!validSizes.contains(breedInfo.getSize())) {
            throw new IllegalArgumentException("体型分类需从预定义列表选择，可选值：" + String.join("/", validSizes));
        }
        
        // 验证描述
        if (validateDescription && breedInfo.getDescription() != null) {
            if (breedInfo.getDescription().length() < 50) {
                throw new IllegalArgumentException("简介描述至少需要50字符");
            }
            if (breedInfo.getDescription().length() > 2000) {
                throw new IllegalArgumentException("简介描述不能超过2000字符");
            }
        }
    }

    /**
     * 验证品种图片
     */
    private void validateBreedImages(List<MultipartFile> images) {
        if (CollectionUtils.isEmpty(images)) {
            throw new IllegalArgumentException("请至少上传1张特征图片");
        }
        if (images.size() > 5) {
            throw new IllegalArgumentException("最多只能上传5张特征图片");
        }
        
        // 验证每张图片
        for (MultipartFile image : images) {
            if (image.isEmpty()) {
                throw new IllegalArgumentException("图片文件不能为空");
            }
            // 文件大小限制
            if (image.getSize() > 2 * 1024 * 1024) { // 2MB
                throw new IllegalArgumentException("图片大小不能超过2MB");
            }
            // 文件格式限制
            String contentType = image.getContentType();
            if (contentType == null || !contentType.startsWith("image/jpeg") && !contentType.startsWith("image/png")) {
                throw new IllegalArgumentException("图片格式仅支持JPG/PNG");
            }
        }
    }

    /**
     * 上传品种图片
     */
    private List<String> uploadBreedImages(List<MultipartFile> images) {
        List<String> imageUrls = new ArrayList<>();
        for (MultipartFile image : images) {
            try {
                // 模拟上传图片并返回URL
                String fileName = UUID.randomUUID().toString() + ".jpg";
                String fileUrl = "https://example.com/images/" + fileName;
                // 创建FileUploadResult对象
                FileUploadUtil.FileUploadResult result = new FileUploadUtil.FileUploadResult(fileUrl);
                imageUrls.add(result.getUrl());
            } catch (Exception e) {
                log.error("上传图片失败", e);
                throw new RuntimeException("上传图片失败: " + e.getMessage(), e);
            }
        }
        return imageUrls;
    }
}
